package com.sc.nft.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.admin.request.*;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.config.sand.SandPayUtil;
import com.sc.nft.dao.UserInfoDao;
import com.sc.nft.dao.UserRelevanceBkDao;
import com.sc.nft.dao.UserRelevanceDao;
import com.sc.nft.entity.AdminUserBankCardVO;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.UserRelevance;
import com.sc.nft.entity.UserRelevanceBk;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.IncomeTypeEnum;
import com.sc.nft.service.UserBankCardService;
import com.sc.nft.service.UserCreatorInfoService;
import com.sc.nft.service.UserInfoService;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 菜单表服务控制器
 *
 * @author rdg
 * @description
 * @since 2022-06-06
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/userManage")
@Api(tags = "App用户管理")
public class AppUserManageController {

    private final UserInfoService userInfoService;

    private final UserCreatorInfoService userCreatorInfoService;

    private final UserBankCardService userBankCardService;

    private final UserRelevanceBkDao userRelevanceBkDao;
    private final UserInfoDao userInfoDao;

    @PostMapping(value = "/pageUserInfo", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取用户列表", notes = "获取用户列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<UserManageVO> pageUserInfo(@Valid @RequestBody UserManageRequest userManageRequest) {
        Page<UserManageVO> page = userInfoService.pageUserInfo(userManageRequest.getUserUuid(), userManageRequest.getNickName(), userManageRequest.getUserTel(), userManageRequest.getStartDate(), userManageRequest.getEndDate(), userManageRequest.getAddress(), userManageRequest.getPageNo(), userManageRequest.getPageSize());
        return PageResult.success(page);
    }

    @PostMapping(value = "/userWithEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取用户持有道具列表", notes = "获取用户持有道具列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<UserEquityPropsSimpleVO> userWithEquityProps(@Valid @RequestBody UserWithEquityPropsRequest request) {
        Page<UserEquityPropsSimpleVO> page = userInfoService.userWithEquityProps(request.getUserId(), request.getFirstTitle(), request.getPageNo(), request.getPageSize());
        return PageResult.success(page);
    }
    @PostMapping(value = "/CollectionByUser", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取用户持仓信息", notes = "获取用户持仓信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<CollectionByUserVO>> collectionByUser(@Valid @RequestBody CollectionByUserRequest request) {
        List<CollectionByUserVO> result = userInfoService.collectionByUser(request.getUserId(), request.getFirstTitle());
        return PageResult.success(result);
    }

    @PostMapping(value = "/CollectionByUserDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取用户持仓信息详情", notes = "获取用户持仓信息详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<CollectionByUserDetailVO>> collectionByUserDetail(@Valid @RequestBody CollectionByUserDetailRequest request) {
        List<CollectionByUserDetailVO> result = userInfoService.collectionByUserDetail(request.getUserId(), request.getCollectionId());

        result.forEach(collectionByUserDetailVO  -> {
            collectionByUserDetailVO.setTypeName(collectionByUserDetailVO.getType().getDescription());
            collectionByUserDetailVO.setFreezingStatusName(collectionByUserDetailVO.getFreezingStatus().getDescription());
                }
        );
        return PageResult.success(result);
    }

    @PostMapping(value = "/mateDaoUserInfo", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "马特DAO-用户列表", notes = "马特DAO-用户列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<UserManageDaoVO> mateDaoUserInfo(@RequestBody UserManageDaoDTO userManageDaoDTO) {
        return PageResult.success(userInfoService.mateDaoUserList(userManageDaoDTO));
    }

    @PostMapping(value = "/UserWithCollectionExport", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "马特DAO-藏品持仓导出", notes = "马特DAO-藏品持仓导出", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<UserWithCollectionExportVO> mateDaoUserWithCollectionExport(@Valid @RequestBody UserWithCollectionRequest userWithCollectionRequest) {
        List<UserWithCollectionSimpleVO> userWithCollectionSimpleVOList = userInfoService.userWithCollectionExport(userWithCollectionRequest.getMarketType());
        UserWithCollectionExportVO userWithCollectionExportVO = new UserWithCollectionExportVO();
        userWithCollectionExportVO
                .setExcelName(userWithCollectionRequest.getMarketType().getDescription() + "持仓统计" + DateUtil.format(DateUtil.date(), "yyyy年MM月dd日") + ".xlsx");
        userWithCollectionExportVO.setUserWithCollectionSimpleVOList(userWithCollectionSimpleVOList);


        return PageResult.success(userWithCollectionExportVO);
    }

    @PostMapping(value = "/getUserDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "马特DAO-用户列表详情", notes = "马特DAO-用户列表详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<UserDetailVO> getUserDetail(@Valid @RequestBody IdRequest request){
        UserDetailVO userDetail = userInfoService.getUserDetail(request.getId());
        return Result.success(userDetail);
    }

    @PostMapping(value = "/saveDaoUserIsPartner", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "马特DAO-修改用户为合伙人", notes = "马特DAO-修改用户为合伙人", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result saveDaoUserIsPartner(@Valid @RequestBody IdRequest idRequest) {
        return PageResult.success(userInfoService.saveDaoUserIsPartner(idRequest.getId()));
    }

    @PostMapping(value = "/userMangeDaoUserInfo", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "马特DAO-用户列表,某个用户详情", notes = "马特DAO-用户列表,某个用户详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<UserMangeDaoUserInfoVO> userMangeDaoUserInfo(@Valid @RequestBody UserMangeDaoUserInfoDTO userManageDaoDTO) {
        return PageResult.success(userInfoService.userMangeDaoUserInfo(userManageDaoDTO));
    }

    @PostMapping(value = "/promotionRewards", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "马特DAO-推广奖励列表", notes = "马特DAO-推广奖励列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<Page<PromotionRewardsVO>> promotionRewards(@Valid @RequestBody PromotionRewardsDTO promotionRewardsDTO) {
        Page<PromotionRewardsVO> promotionRewardsVOPage = userInfoService.promotionRewards(promotionRewardsDTO);
        promotionRewardsVOPage.getRecords().forEach(promotionRewardsVO -> {
            IncomeTypeEnum byId = IncomeTypeEnum.getById(promotionRewardsVO.getIncomeType());
            if (BeanUtil.isEmpty(byId)) {
                promotionRewardsVO.setIncomeName("未知");
            } else {
                promotionRewardsVO.setIncomeName(byId.getDescription());
            }
        });
        return PageResult.success(promotionRewardsVOPage);
    }

    @PostMapping(value = "/mateUserMangeDaoGeneralEarningsDirectlyList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "马特DAO-用户信息,直推列表", notes = "马特DAO-用户信息,直推列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<Page<MaTeUserMangeDaoGeneralEarningsDirectlyListVO>> mateUserMangeDaoGeneralEarningsDirectlyList(@Valid @RequestBody MaTeUserMangeDaoGeneralEarningsDirectlyDTO maTeUserMangeDaoGeneralEarningsDirectlyDTO) {
        return PageResult.success(userInfoService.mateUserMangeDaoGeneralEarningsDirectlyList(maTeUserMangeDaoGeneralEarningsDirectlyDTO));
    }

    @PostMapping(value = "/maTeUserMangeDaoGeneralEarningsIndirectList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "马特DAO-用户信息,间推列表", notes = "马特DAO-用户信息,间推列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<Page<MaTeUserMangeDaoGeneralEarningsIndirectListVO>> maTeUserMangeDaoGeneralEarningsIndirectList(@RequestBody MaTeUserMangeDaoGeneralEarningsDirectlyDTO maTeUserMangeDaoGeneralEarningsDirectlyDTO) {
        return PageResult.success(userInfoService.maTeUserMangeDaoGeneralEarningsIndirectList(maTeUserMangeDaoGeneralEarningsDirectlyDTO));
    }

    @PostMapping(value = "/userInfoEarningsList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "用户收益列表", notes = "用户收益列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<Page<UserInfoEarningsVO>> userInfoEarningsList(@RequestBody EarningsListDTO earningsListDTO) {
        return PageResult.success(userInfoService.userInfoEarningsList(earningsListDTO));
    }

    @PostMapping(value = "/calculationReward", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "计算奖励", notes = "计算奖励", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<CalculationRewardVO> calculationReward(@RequestBody CalculationRewardDTO calculationRewardDTO) {
        return Result.success(userInfoService.calculationReward(calculationRewardDTO));
    }

    @PostMapping(value = "/distributionRewards", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "发放奖励", notes = "发放奖励", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result distributionRewards(@Valid @RequestBody DistributionRewardsDTO distributionRewardsDTO) {
        return Result.success(userInfoService.distributionRewards(distributionRewardsDTO));
    }

    @PostMapping(value = "/interestsList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "权益列表", notes = "权益列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<InterestsListVO> interestsList() {
        return Result.success(userInfoService.interestsList());
    }

    @PostMapping(value = "/interestsSave", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "权益列表修改", notes = "权益列表修改", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<Boolean> interestsSave(@RequestBody List<InterestsSaveDTO> interestsSaveDTO) {
        return Result.success(userInfoService.interestsSave(interestsSaveDTO));
    }

    @PostMapping(value = "/specialReward", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "特殊奖励列表", notes = "特殊奖励列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<Page<SpecialRewardVO>> specialReward(@RequestBody SpecialRewardDTO specialRewardDTO) {
        Page<SpecialRewardVO> specialRewardVOPage = userInfoService.specialReward(specialRewardDTO);
        specialRewardVOPage.getRecords().forEach(specialRewardVO -> {
            IncomeTypeEnum byId = IncomeTypeEnum.getById(specialRewardVO.getIncomeType());
            if (BeanUtil.isEmpty(byId)) {
                specialRewardVO.setIncomeName("未知");
            } else {
                specialRewardVO.setIncomeName(byId.getDescription());
            }
        });
        return PageResult.success(specialRewardVOPage);
    }

    @PostMapping(value = "/rewardType", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "奖励筛选类型", notes = "奖励筛选类型", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<RewardTypeVO>> rewardType() {
        List<RewardTypeVO> rewardTypeVOS = new ArrayList<>();
        for (IncomeTypeEnum value : IncomeTypeEnum.values()) {
            RewardTypeVO rewardTypeVO = new RewardTypeVO();
            rewardTypeVO.setIncomeType(value.getCode());
            rewardTypeVO.setIncomeName(value.getDescription());
            rewardTypeVOS.add(rewardTypeVO);
        }
        return Result.success(rewardTypeVOS);
    }

    @PostMapping(value = "/userRelevanceDataSynchronism", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "用户关联数据同步", notes = "用户关联数据同步", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result userRelevanceDataSynchronism() {
        // 处理第几段的数据
        int q = 1;
        // 执行到了第几个用户的数据
        int w = 0;
        while (true) {
            log.info("处理第{}条数据", w);
            QueryWrapper<UserInfo> queryWrapper = new QueryWrapper();
            queryWrapper.last(StrUtil.format("limit {},1", w));
            queryWrapper.select("id");
//            UserInfo userInfo = (UserInfo) new UserInfo().selectOne(queryWrapper);
            UserInfo userInfo = userInfoDao.getOne(queryWrapper);
            if (BeanUtil.isEmpty(userInfo)) {
                break;
            }
            dataBaseSaveRecursion(userInfo.getId(), q, userInfo.getId());
            w++;
        }
        log.info("重置完成");
        return Result.success();
    }

    public void dataBaseSaveRecursion(Long userId, Integer lv, Long originalId) {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper();
        queryWrapper.eq("recommend_user_id", userId);
        queryWrapper.eq("bind_flag", true);
        queryWrapper.select("id");
//        List<UserInfo> list = (List<UserInfo>) new UserInfo().selectList(queryWrapper);
        List<UserInfo> list = userInfoDao.list(queryWrapper);
        dataBaseSave(list, originalId, lv);
        for (UserInfo info : list) {
            dataBaseSaveRecursion(info.getId(), lv + 1, originalId);
        }
    }

    public void dataBaseSave(List<UserInfo> list, Long userId, Integer lv) {
        List<List<UserInfo>> parts = Lists.partition(list, 1000);
        for (List<UserInfo> part : parts) {
            List<UserRelevanceBk> userRelevances = new ArrayList<>();
            for (UserInfo userInfo : part) {
                UserRelevanceBk userRelevance = new UserRelevanceBk();
                userRelevance.setUserId(userId);
                userRelevance.setRelevanceId(userInfo.getId());
                userRelevance.setLv(lv);
                userRelevance.setCreateTime(new Date());
                userRelevance.setUpdateTime(new Date());
                userRelevances.add(userRelevance);
            }
            userRelevanceBkDao.saveBatch(userRelevances);
        }
    }

    @PostMapping(value = "/updateUserInformation", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "修改用户信息", notes = "添加用户", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result updateUserInformation(@Valid @RequestBody UpdateUserInformationRequest updateUserInformationRequest) {
        userInfoService.updateUserInformation(updateUserInformationRequest.getId(), updateUserInformationRequest.getNickName(),
                updateUserInformationRequest.getAvatarImg(), updateUserInformationRequest.getIsFreeze(), updateUserInformationRequest.getGiftPermission());
        return Result.success();
    }

    @PostMapping(value = "/getUserCreatorList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "修改藏品信息用的作者列表", notes = "修改藏品信息用的作者列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<UserCreatorListVO> getUserCreatorList(@Valid @RequestBody PageRequest request) {
        Page<UserCreatorListVO> page = userCreatorInfoService.getUserCreatorList(request.getPageNo(), request.getPageSize());
        return PageResult.success(page);
    }

    @PostMapping(value = "/getUserBankCard", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "用户银行卡信息", notes = "用户银行卡信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<AdminUserBankCardVO>> getUserBankCard(@Valid @RequestBody IdRequest request) {
        return Result.successColl(userBankCardService.getByUserId(request.getId()), AdminUserBankCardVO.class);
    }

    @SneakyThrows
    @ApiOperation(value = "杉德商户余额", notes = "杉德商户余额", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/shanDePayBalanceOutStanding", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result shanDePayBalanceOutStanding() {
        JSONObject s = new JSONObject();
        s.put("version", "01");
        s.put("productId", "00000004");
        s.put("tranTime", DateUtil.format(new Date(), "yyyyMMddHHmmss"));
        s.put("orderCode", IdUtil.getSnowflake().nextId());
        JSONObject jsonObject = SandPayUtil.requestServer(s);
        String creditAmt = (String) jsonObject.get("creditAmt");
        String balance = (String) jsonObject.get("balance");
        jsonObject.put("creditAmt", Convert.toBigDecimal(creditAmt).divide(Convert.toBigDecimal(100)).stripTrailingZeros().toString());
        jsonObject.put("balance", Convert.toBigDecimal(balance).divide(Convert.toBigDecimal(100)).stripTrailingZeros().toString());
        return Result.success(jsonObject);
    }

}
